package hibernatemock;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import org.hibernate.Session;

public class Builder {

	private Builder() {

	}

	public static HibernateMock create(Session session, HibernateMock hibernateMock) {
		validate(session);
		InstanceFactory instanceFactory = new InstanceFactory();
		SetupBuilder setupBuilder = setupBuilder(instanceFactory);
		defaultSetup(setupBuilder);
		instanceFactory.setSetups(setupBuilder.getSetups());
		
		Persistence persistence = persistence(session);
		TreeProcessor treeProcessor = treeProcessor(instanceFactory);
		hibernateMock(hibernateMock, setupBuilder, persistence, treeProcessor);
		return hibernateMock;
	}

	private static void hibernateMock(HibernateMock hibernateMock, SetupBuilder setupBuilder, Persistence persistence, TreeProcessor treeProcessor) {
		hibernateMock.setTreeProcessor(treeProcessor);
		hibernateMock.setSetupBuilder(setupBuilder);
		hibernateMock.setPersistence(persistence);
	}

	private static TreeProcessor treeProcessor(InstanceFactory instanceFactory) {
		TreeProcessor treeProcessor = new TreeProcessor();
		treeProcessor.setAvoidCyclic(new HashMap<Class<?>, Object>());
		treeProcessor.setMappedFieldsLookup(new MappedFieldsLookup());
		treeProcessor.setInstanceFactory(instanceFactory);
		treeProcessor.setEntitiesToPersist(new ArrayList<Object>());
		return treeProcessor;
	}

	private static Persistence persistence(Session session) {
		Persistence persistence = new Persistence();
		persistence.setSession(session);
		return persistence;
	}


	private static void defaultSetup(SetupBuilder setupBuilder) {
		DefaultSetup defaultSetup = new DefaultSetup();
		defaultSetup.setSetupBuilder(setupBuilder);
		defaultSetup.fillWithDefaults();
	}

	private static SetupBuilder setupBuilder(InstanceFactory instanceFactory) {
		SetupBuilder setupBuilder = new SetupBuilder();
		setupBuilder.setSetups(new HashSet<Setup>());
		setupBuilder.setInstanceFactory(instanceFactory);
		return setupBuilder;
	}

	private static void validate(Session session) {
		if (!session.isOpen())
			throw new RuntimeException("EntityManager/Session is not open. It should be open.");
//		if (!session.getTransaction().isActive())
//			session.getTransaction().begin();
	}

}
